package com.ybt.communicate.core.manager;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;

import org.apache.log4j.Logger;

import com.ybt.communicate.core.IProtocol;
import com.ybt.communicate.core.configration.IProtocolConfig;
import com.ybt.communicate.core.exception.ProtocolException;
import com.ybt.communicate.core.factory.IProtocolFactory;
import com.ybt.communicate.core.parser.impl.CommonProtocolParser;
import com.ybt.configration.IYBTConfigration;
import com.ybt.configration.YBTConfigration;
import com.ybt.pub.Utils;

public class ProtocolManager {
    private static Logger logger = Logger.getLogger(ProtocolManager.class);
    private static volatile ProtocolManager manager;
    private static String CONFIG_DIR;
    private static String CONFIG_DIR_AUTO;
    private Map<String, IProtocol> pros;

    private ProtocolManager() {
        CONFIG_DIR = YBTConfigration.getInstance().getProperty(
                IYBTConfigration.WORKFLOW_DEPLOY_PATH) + File.separator + "protocols";
        CONFIG_DIR_AUTO = CONFIG_DIR + File.separator + "autobak";

        pros = new HashMap<String, IProtocol>();
    }

    public static ProtocolManager getInstance() {
        if (manager == null) {
            synchronized (ProtocolManager.class) {
                if (manager == null) {
                    manager = new ProtocolManager();
                }
            }
        }
        return manager;
    }

    public IProtocol getProtocol(String protocolId) {
        return pros.get(protocolId);
    }

    public boolean startProtocol(String protocolId) throws ProtocolException {
        IProtocol p = pros.get(protocolId);
        if (p == null) {
            throw new ProtocolException("unsupport protocol [" + protocolId
                    + "]");
        }
        p.start();
        return true;
    }

    public boolean stopProtocol(String protocolId) throws ProtocolException {
        IProtocol p = pros.get(protocolId);
        if (p == null) {
            throw new ProtocolException("unsupport protocol [" + protocolId
                    + "]");
        }
        p.stop();
        return true;
    }

    public boolean registerProtocol(String configuration)
            throws ProtocolException {
        ByteArrayInputStream temp = new ByteArrayInputStream(configuration
                .getBytes());
        return registerProtocol(temp);
    }

    public boolean registerProtocol(InputStream configuration)
            throws ProtocolException {

        // 解析静态配置
        IProtocolConfig config = new CommonProtocolParser()
                .parse(configuration);

        // 获取协议工厂
        IProtocolFactory factory = ProtocolTypeManager.getInstance()
                .getProtocolFactory(config.getProtocolType());

        // 创建运行时协议
        IProtocol p = factory.createProtocol(config);

        // 启动协议
        p.start();

        this.pros.put(config.getProtocolId(), p);
        /*
         * try{
         * XmlUtil.saveXml(CONFIG_DIR+File.separator+config.getProtocolId()+".xml",
         * configuration, null);
         * XmlUtil.saveXml(CONFIG_DIR_AUTO+File.separator+config.getProtocolId()+".xml",
         * configuration, null); }catch(Exception e){ logger.error("save
         * protocol configuration file error : " + config.getProtocolId(), e); }
         */

        return true;
    }

    public boolean unRegisterProtocol(String protocolId)
            throws ProtocolException {
        IProtocol p = pros.remove(protocolId);
        if (p == null) {
            logger.warn("unsupport protocol [" + protocolId + "]");
            return false;
        }

        // 停止协议
        p.stop();

        // 删除协议对应的配置文件
        Utils.deleteFile(CONFIG_DIR + File.separator + protocolId + ".xml");
        Utils
                .deleteFile(CONFIG_DIR_AUTO + File.separator + protocolId
                        + ".xml");

        return true;
    }

    public void startAllProtocol() {

        File dir = new File(CONFIG_DIR);
        if (!dir.exists()) {
            dir.mkdirs();
        }

        File[] connFiles = dir.listFiles(new FilenameFilter() {
            public boolean accept(File arg0, String arg1) {
                // TODO Auto-generated method stub
                if (arg1.matches("(.)*\\.xml"))
                    return true;
                return false;
            }
        });

        if (connFiles == null || connFiles.length == 0) {
            // 没有配置文件
            logger.debug("there is no protocol configration files in direct : "
                    + CONFIG_DIR);
            return;
        }

        // 逐个处理协议配置文件
        for (File connFile : connFiles) {
            // 注册connector
            InputStream s = null;
            try {
                s = new FileInputStream(connFile);
                logger.debug("registe the protocol defined in file : "
                        + connFile.getAbsoluteFile());
                registerProtocol(s);
                Utils.copyFile(connFile, CONFIG_DIR + File.separator
                        + "autobak");
            } catch (Exception e) {
                logger.error(e, e);
            } finally {
                if (s != null) {
                    try {
                        s.close();
                    } catch (IOException e) {
                        // TODO Auto-generated catch block
                        logger
                                .error(
                                        "close file error when load protocol from local disk",
                                        e);
                    }
                }
            }
        }

    }
}
